package com.hatricks.is.base.threadpool;//package com.hatricks.base.threadpool;
//
//import cn.hutool.core.util.IdUtil;
//import cn.hutool.extra.spring.SpringUtil;
//import com.hatricks.base.dto.com.hs.groovy.Test;
//import com.hatricks.base.mapper.TestMapper;
//import lombok.Builder;
//import org.mybatis.spring.transaction.SpringManagedTransaction;
//import org.springframework.aop.framework.AopProxyUtils;
//import org.springframework.jdbc.datasource.DataSourceTransactionManager;
//import org.springframework.stereotype.Component;
//import org.springframework.transaction.TransactionDefinition;
//import org.springframework.transaction.TransactionStatus;
//import org.springframework.transaction.annotation.Transactional;
//import org.springframework.transaction.support.DefaultTransactionDefinition;
//import org.springframework.transaction.support.TransactionSynchronization;
//import org.springframework.transaction.support.TransactionSynchronizationManager;
//
//import javax.annotation.Resource;
//import javax.sql.DataSource;
//import java.util.*;
//import java.util.concurrent.CompletableFuture;
//import java.util.concurrent.ExecutionException;
//import java.util.concurrent.ExecutorService;
//import java.util.concurrent.Executors;
//import java.util.concurrent.atomic.AtomicBoolean;
//
///**
// * @packageName: com.hatricks.base.threadpool
// * @className: MultiThreadTransaction
// * @author: yanyh yanyh@glodon.com
// * @date: 2023/7/27 8:20
// * @description:
// */
//@Component
//public class MultiThreadTransaction {
//
//    //TransactionDefinition 事务的隔离级别 事务的传播行为 事务的超时时间  是否为只读事务
//    //TransactionStatus 事务的状态 事务已完成 事务回滚 等
//    /**
//     * 当前事务是否是新事务
//     * 当前事务是否结束
//     * 当前事务是否需要回滚(通过标记来判断,因此我也可以在业务流程中手动设置标记为true,来让事务在没有发生异常的情况下进行回滚)
//     * 当前事务是否设置了回滚点(savePoint)
//     */
//    @Resource
//    DataSource dataSource;
//
//    @Resource
//    TestMapper testMapper;
//
//    @SuppressWarnings("rawtypes")
//    public void transactionController(List<Runnable> runnables) {
//        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
//        ExecutorService executorService = Executors.newFixedThreadPool(5);
//
//        AtomicBoolean ex = new AtomicBoolean();
//
//        List<CompletableFuture> taskFutureList = new ArrayList<>(runnables.size());
//        List<TransactionStatus> transactionStatusList = new ArrayList<>(runnables.size());
//        List<TransactionResource> transactionResources = new ArrayList<>(runnables.size());
//
//        for (int i = 0; i < runnables.size(); i++) {
//            int fi = i;
//            taskFutureList.add(CompletableFuture.runAsync(
//                    () -> {
//                        try {
//                            //1.开启新事务
//                            transactionStatusList.add(openNewTransaction(transactionManager));
//                            //2.copy事务资源
//                            transactionResources.add(TransactionResource.copyTransactionResource());
//                            //3.异步任务执行
//                            runnables.get(fi).run();
//                        } catch (Throwable throwable) {
//                            //打印异常
//                            throwable.printStackTrace();
//                            //其中某个异步任务执行出现了异常,进行标记
//                            ex.set(Boolean.TRUE);
//                            //其他任务还没执行的不需要执行了
//                            taskFutureList.forEach(completableFuture -> completableFuture.cancel(true));
//                        }
//                    }, executorService)
//            );
//        }
//
//        try {
//            //阻塞直到所有任务全部执行结束---如果有任务被取消,这里会抛出异常滴,需要捕获
//            CompletableFuture.allOf(taskFutureList.toArray(new CompletableFuture[]{})).get();
//        } catch (InterruptedException | ExecutionException e) {
//            e.printStackTrace();
//        }
//
//        //发生了异常则进行回滚操作,否则提交
//        if (ex.get()) {
//            System.out.println("发生异常,全部事务回滚");
//            for (int i = 0; i < runnables.size(); i++) {
//                transactionResources.get(i).autoWiredTransactionResource();
//                transactionManager.rollback(transactionStatusList.get(i));
//                transactionResources.get(i).removeTransactionResource();
//            }
//        } else {
//            System.out.println("全部事务正常提交");
//            for (int i = 0; i < runnables.size(); i++) {
//                transactionResources.get(i).autoWiredTransactionResource();
//                transactionManager.commit(transactionStatusList.get(i));
//                transactionResources.get(i).removeTransactionResource();
//            }
//        }
//    }
//
//    public void test() {
//        List<Runnable> runnables = new ArrayList<>();
//
//        runnables.add(() -> {
//            com.hs.groovy.Test entity = new com.hs.groovy.Test();
//            entity.setId(12);
//            entity.setA("a");
//            entity.setB("b");
//            testMapper.insert(entity);
//        });
//
//        runnables.add(() -> {
//            com.hs.groovy.Test entity = new com.hs.groovy.Test();
//            entity.setId(13);
//            entity.setA("a");
//            entity.setB("c");
//            testMapper.insert(entity);
//            throw new RuntimeException("你好哇 有异常了");
//        });
//        SpringUtil.getBean(MultiThreadTransaction.class).transactionController(runnables);
//    }
//
//    private TransactionStatus openNewTransaction(DataSourceTransactionManager transactionManager) {
//        //JdbcTransactionManager根据TransactionDefinition信息来进行一些连接属性的设置
//        //包括隔离级别和传播行为等
//        DefaultTransactionDefinition transactionDef = new DefaultTransactionDefinition();
//        //开启一个新事务---此时autocommit已经被设置为了false,并且当前没有事务,这里创建的是一个新事务
//        return transactionManager.getTransaction(transactionDef);
//    }
//
//    /**
//     * 保存当前事务资源,用于线程间的事务资源COPY操作
//     */
//    @Builder
//    private static class TransactionResource {
//        //事务结束后默认会移除集合中的DataSource作为key关联的资源记录
//        private Map<Object, Object> resources;
//        //下面五个属性会在事务结束后被自动清理,无需我们手动清理
//        private Set<TransactionSynchronization> synchronizations;
//        private String currentTransactionName;
//        private Boolean currentTransactionReadOnly;
//        private Integer currentTransactionIsolationLevel;
//        private Boolean actualTransactionActive;
//
//        public static TransactionResource copyTransactionResource() {
//            return TransactionResource.builder()
//                    //返回的是不可变集合
//                    .resources(TransactionSynchronizationManager.getResourceMap())
//                    //如果需要注册事务监听者,这里记得修改--我们这里不需要,就采用默认负责--spring事务内部默认也是这个值
//                    .synchronizations(new LinkedHashSet<>())
//                    .currentTransactionName(TransactionSynchronizationManager.getCurrentTransactionName())
//                    .currentTransactionReadOnly(TransactionSynchronizationManager.isCurrentTransactionReadOnly())
//                    .currentTransactionIsolationLevel(TransactionSynchronizationManager.getCurrentTransactionIsolationLevel())
//                    .actualTransactionActive(TransactionSynchronizationManager.isActualTransactionActive())
//                    .build();
//        }
//
//        public void autoWiredTransactionResource() {
//            resources.forEach(TransactionSynchronizationManager::bindResource);
//            //如果需要注册事务监听者,这里记得修改--我们这里不需要,就采用默认负责--spring事务内部默认也是这个值
//            TransactionSynchronizationManager.initSynchronization();
//            TransactionSynchronizationManager.setActualTransactionActive(actualTransactionActive);
//            TransactionSynchronizationManager.setCurrentTransactionName(currentTransactionName);
//            TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(currentTransactionIsolationLevel);
//            TransactionSynchronizationManager.setCurrentTransactionReadOnly(currentTransactionReadOnly);
//        }
//
//        public void removeTransactionResource() {
//            //事务结束后默认会移除集合中的DataSource作为key关联的资源记录
//            //DataSource如果重复移除,unbindResource时会因为不存在此key关联的事务资源而报错
//            resources.keySet().forEach(key -> {
//                if (!(key instanceof DataSource)) {
//                    TransactionSynchronizationManager.unbindResource(key);
//                }
//            });
//        }
//    }
//
//}
